Flex端依次向PHP客户端发送两个Request, 由于php端处理第一个Request时存在bug, 由于Keep-Alive, 第二个Request会先接收第一个Request的残局, 造成第二个Request在FireFox下出现异常.
涉及到的内容: PHP, Http Header, Flex URLLoader URLRequest, Keep-Alive, Apache AccessLog, FireFox, Firebug(除了Flex我比较熟之外其他基本上都是懂一点, 所以下面说辞可能会与具体语言/工具有所出入).
起因非常简单: php端一个while的condition没有随着循环而++.
详细描述:
为了测试服务器速度, 我们用Flex + PHP写了一个测试程序, 测试一组服务器的上传下载速度, Debug时很稳定, 如图:
IE下测试效果很好, 但在Build后放在FireFox上测试, Firefox的pulugin-container就占到若干G内存. 以前我只写过卡死浏览器的程序, 还不曾写过直接死机的程序, 结果昨晚dubug时竟然搞死我的电脑一次.
Flex端会通过URLLoader及URLRequest与PHP进行交互, 我们先从服务器读取1M的数据, 计算速度, 然后将数据发送到php端保存. 整个客户端的过程就是: Download, Report.
PHP端收到Download请求后, 会生成一个1M的文件返回到Flex端; 收到Report请求后会保存速度等参数, 并会返回ip所在地.
在使用FireFox进行测速时, 发现在Report后进入假死状态, 直到flash crash或浏览器死掉, 于是使用Firebug查看Request情况, 如图:
非常不可思议的是发现Report中返回的数据竟然超大, 而且越来越大, 毫无停止的迹象. (后来该用FireFox浏览器进行Debug, 在监听Report.ProgressEvent时发现 bytesTotal也在不断的长大)
费解啊费解, 后来发现在Flex端如果在Download结束后, 暂停上2秒(及以上), 再进行report就会正常report并返回ip所在地.
怀疑可能是Report Action处理有问题? 于是查看了Apahce的AccessLog, 发现只有Download的Access记录, 而无Report的Access记录. 我干啊..
于是猜想: 可能是跟浏览器的Keep-Alive有关
仔细排查了PHP端代码, 发现在生成文件的一个while中, 参数没有++, 导致在Download时, 虽然打算创建1M的文件, 但实际上while停不下一直会增大文件…
但Download的Header里明确了文件大小信息:
header("Content-Length: ".(string)($downloadSize));
所以浏览器跟URLRequest都只会下载1M的数据, 但服务器仍在while循环, 文件仍在不断变大….
猜想可能是由于FireFox的keep-alive, 在Report请求时, 发现TCP连接中仍有活动的connection, 于是先继续接受TCP已接收的数据, 也就是Download的1M数据之外的数据, 于是Report开始后实际上还是在下载1M之外未完的数据. 由于1M之外的数据读不完, 下了大量数据, 于是关掉FireFox或plugin-container进程, Firebug中看到的Report Request实际仍没有发送到服务器端, 于是造成了Report收拾Download残局的现状.
如此折腾下来, 看来只需修复php端bug就好, 果然搞定.
重复验证:
php端处理DownloadAction代码中, 创建完毕1M数据后, echo ‘liguoliang.com’;
也就是这个几个字符会继续发送到客户机, 但不会被浏览器处理(Header中定义了文件下载大小为1M), 因此多余的’liguoliang.com’ 会在第二次Request后首先从客户机读取, 然后再向服务器端请求(由于此前文件不断变大, 所以等不到收拾完Download Request残局就crash了).
果然, 查看Apache的Access log, 正常, 有两个记录, 再看Firebug:
果然, 先收拾了上一把的残局, 搞的下一把都异常了.
这个bug出现的条件:
测试服务器在本机, 所以操作都很快, 眨眼就下完1M数据, 然后会keep-alive, report Request会收拾前一个有问题的Request的残局. 如果测试服务器在外部, 或两个Request间隔大于2秒(前一个结束到后一个开始)第二个Request会直接去请求服务器, 而不是先吃剩饭, 造成异常.
Vi Reference Card 常用命令表 <->
// Proudly powered by Apache, PHP, MySQL, WordPress, Bootstrap, etc,.